//-----------------------------------------
//	Cartoon
//-----------------------------------------

//------------------
//--- Parameters ---
float4x4 World;
float4x4 View;
float4x4 Projection;

// The light direction is shared between the Lambert and Toon lighting techniques.
float3 LightDirection = normalize(float3(1, 1, 1));

// Settings controlling the Lambert lighting technique.
float3 DiffuseLight = 0.5;
float3 AmbientLight = 0.5;

// Settings controlling the Toon lighting technique.
float ToonThresholds[2] = { 0.8, 0.4 };
float ToonBrightnessLevels[3] = { 1.3, 0.9, 0.5 };

bool TextureEnabled;
texture Texture;

sampler Sampler = sampler_state
{
    Texture = (Texture);
    
    MinFilter = Linear;
    MagFilter = Linear;
    MipFilter = Linear;
    
    AddressU = Wrap;
    AddressV = Wrap;
};

//------------------
//--- Structures ---
struct VertexShaderInput
{
	float4 Position : POSITION;
	float3 Normal : NORMAL;
	float2 TextureCoordinate : TEXCOORD0;
};

struct VertexShaderOutput 
{
   float4 Position : POSITION0;
   float2 TextureCoordinate : TEXCOORD0;
   float LightAmount : TEXCOORD1;
};

struct PixelShaderInput
{
	float2 TextureCoordinate : TEXCOORD0;
    float LightAmount : TEXCOORD1;
};

//--------------------
//--- VertexShader ---
// Vertex shader shared between the Lambert and Toon lighting techniques.
VertexShaderOutput LightingVertexShader(VertexShaderInput input)
{
    VertexShaderOutput output;

    // Apply camera matrices to the input position.
    output.Position = mul(mul(mul(input.Position, World), View), Projection);
    
    // Copy across the input texture coordinate.
    output.TextureCoordinate = input.TextureCoordinate;

    // Compute the overall lighting brightness.
    float3 worldNormal = mul(input.Normal, World);
    
    output.LightAmount = dot(worldNormal, LightDirection);
    
    return output;
}

//-------------------
//--- PixelShader ---
float4 ToonPixelShader(PixelShaderInput input) : COLOR0
{
    float4 color = TextureEnabled ? tex2D(Sampler, input.TextureCoordinate) : 0;
    
    float light;

    if (input.LightAmount > ToonThresholds[0])
        light = ToonBrightnessLevels[0];
    else if (input.LightAmount > ToonThresholds[1])
        light = ToonBrightnessLevels[1];
    else
        light = ToonBrightnessLevels[2];
                
    color.rgb *= light;
    
    return color;
}

//------------------
//--- Techniques ---
technique PerPixellighting
{
    pass P0
    {
          VertexShader = compile vs_2_0 LightingVertexShader();
          PixelShader = compile ps_2_0 ToonPixelShader();
    }
}